package com.boot2.core.utils;


import java.text.Collator;

/**
* @author zhangweilin
* @date 2020/9/25 10:36
* @Description:  按字符串（包含数字）自然排序，其中数字按自然数字排
 * 用法:
 *     deviceSimplificationList.sort((o1, o2) -> AlphanumComparator.compare(o1.getName(), o2.getName()));
 *  前:
 * e.getName() = aaa10aaa
 * e.getName() = aaa12aaa
 * e.getName() = aaa9aaa
 * e.getName() = aaa8aaa
 * e.getName() = aaa20aaa
 * e.getName() = aaa21aaa
 * e.getName() = aaa3aaa
 *  后:
 * e.getName() = aaa3aaa
 * e.getName() = aaa8aaa
 * e.getName() = aaa9aaa
 * e.getName() = aaa10aaa
 * e.getName() = aaa12aaa
 * e.getName() = aaa20aaa
 * e.getName() = aaa21aaa
*/
public class AlphanumComparatorUtil {

	private static final Collator collator = Collator.getInstance(java.util.Locale.CHINA);

	public static int compare(String s1, String s2) {
		/*
		if (ObjectUtil.isBlank(s1) && ObjectUtil.isBlank(s2)) {
			return 0;
		}
		if (ObjectUtil.isBlank(s1)) {
			return -1;
		}
		if (ObjectUtil.isBlank(s2)) {
			return 1;
		}
		*/
		int thisMarker = 0;
		int thatMarker = 0;
		int s1Length = s1.length();
		int s2Length = s2.length();

		while (thisMarker < s1Length && thatMarker < s2Length) {
			String thisChunk = getChunk(s1, s1Length, thisMarker);
			thisMarker += thisChunk.length();

			String thatChunk = getChunk(s2, s2Length, thatMarker);
			thatMarker += thatChunk.length();

			// If both chunks contain numeric characters, sort them numerically
			int result;
			if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) {
				// Simple chunk comparison by length.
				int thisChunkLength = thisChunk.length();
				result = thisChunkLength - thatChunk.length();
				// If equal, the first different number counts
				if (result == 0) {
					for (int i = 0; i < thisChunkLength; i++) {
						result = thisChunk.charAt(i) - thatChunk.charAt(i);
						if (result != 0) {
							return result;
						}
					}
				}
			} else {
				result = collator.compare(thisChunk, thatChunk);
				//result = thisChunk.compareTo(thatChunk);
			}

			if (result != 0) {
				return result;
			}
		}
		return s1Length - s2Length;
	}

	private static boolean isDigit(char ch) {
		return ch >= 48 && ch <= 57;
	}

	/**
	 * Length of string is passed in for improved efficiency (only need to
	 * calculate it once) *
	 */
	private static String getChunk(String s, int slength, int marker) {
		StringBuilder chunk = new StringBuilder();
		char c = s.charAt(marker);
		chunk.append(c);
		marker++;
		if (isDigit(c)) {
			while (marker < slength) {
				c = s.charAt(marker);
				if (!isDigit(c)) {
					break;
				}
				chunk.append(c);
				marker++;
			}
		} else {
			while (marker < slength) {
				c = s.charAt(marker);
				if (isDigit(c)) {
					break;
				}
				chunk.append(c);
				marker++;
			}
		}
		return chunk.toString();
	}

}
